#include "udp_io.h"
#ifdef WIN32
#define usleep(x) Sleep(x)
#endif
#ifdef __linux__
#include <stdexcept>
#endif
#include "Log.h"
#include "record_queue.h"

UdpIO::UdpIO(std::string addr/*="127.0.0.1"*/,int port/*=60004*/)
    : running(true)
{
    acl_lib_init();
    ptr_rq = RecordQueue::getInstance();
    char  local[64]={0};
	snprintf(local, sizeof(local), "%s:%d",addr.c_str(),port);
    local_addr = std::string(local);
}

UdpIO::~UdpIO()
{
    running = false;
}

void* UdpIO::run()
{
    ACL_VSTREAM *stream = acl_vstream_bind(local_addr.c_str(), 2, 0);  /* 绑定 UDP 套接口 */
    if (stream == NULL) {
		CLogger::createInstance()->Log(MsgError,"acl_vstream_bind %s error %s int UdpIO::run()",
			local_addr.c_str(), acl_last_serror());
		return NULL;
	}
    printf("bind udp addr %s ok\r\n", local_addr.c_str());
    unsigned char buf[256] = {0};
    int ret = 0;
    // unsigned int index = 0;
	while (running)
    {
        ret = acl_vstream_read(stream, buf, 256);
		if (ret == ACL_VSTREAM_EOF) {
			printf("acl_vstream_read error %s\r\n",
				acl_last_serror());
			//重置udp
			acl_vstream_close(stream);
			stream = acl_vstream_bind(local_addr.c_str(), 2, 0);  /* 绑定 UDP 套接口 */
			if (stream == NULL) {
				CLogger::createInstance()->Log(MsgError,"acl_vstream_bind %s error %s int UdpIO::run()",
					local_addr.c_str(), acl_last_serror());
				break;
			}
		} else{
			buf[ret] = 0;
            // printf("rec[%u],len[%d]:\n",index++,ret);
			// for (int i = 0; i < ret; i++)
			// {
			// 	printf("%02X", buf[i]);
			// }
			// printf("\n");
            AddFrameDef((const unsigned char *)buf,ret);
        }
        usleep(10);
    }
    
    acl_vstream_close(stream);
    return NULL;
}

int UdpIO::AddFrameDef(const unsigned char *pBuf, int len)
{
	try {
		unsigned char type = pBuf[0];
		int idx = 1;
		switch (type)
		{
		case 0XF8://查询
		{
			int rlen = pBuf[idx++];
			rlen += (pBuf[idx++] << 8);
			if ((rlen + 1) != len) 
			{
				break;
			}
            int psize = pBuf[idx++];
			psize += (pBuf[idx++] << 8);
			if ((17*psize + 6) != len) 
			{
				break;
			}
            for (int i = 0; i < psize; ++i) 
            {
                //devid
                int devid = 0;
                devid += pBuf[idx++];
                devid += (pBuf[idx++] << 8);
                devid += (pBuf[idx++] << 16);
                devid += (pBuf[idx++] << 24);
                //pid
                int pID = 0;
                pID += pBuf[idx++];
                pID += (pBuf[idx++] << 8);
                pID += (pBuf[idx++] << 16);
                pID += (pBuf[idx++] << 24);
                //sec
                unsigned int sec = 0;
                sec += pBuf[idx++];
                sec += (pBuf[idx++] << 8);
                sec += (pBuf[idx++] << 16);
                sec += (pBuf[idx++] << 24);
                //usec
                int usec = pBuf[idx++];
                //val
                float Value = float(0.0);
                unsigned char* fval = (unsigned char*)&Value;
                fval[3] = pBuf[idx++];
                fval[2] = pBuf[idx++];
                fval[1] = pBuf[idx++];
                fval[0] = pBuf[idx++];
                fval = NULL;
                //
                ptr_rq->addItem(devid,pID,sec*1000+usec,Value);
                // Print_NOTICE("read data 0XF8:devID[%d],pID[%d],sec[%d],usec[%d],val[%.3f]\n"
				// , devid, pID, sec, usec, Value);
            }
			//end
			unsigned char endflag = pBuf[idx++];
			if (0XFF != endflag)
			{
				Print_WARN("error end for frame data in AddFrameDef\r\n");
			}
		}
		break;
		default:
		{
			char warBuf[128] = { 0 };
			sprintf(warBuf,"UdpIO::AddFrameDef For Unkown Type(%02X)", type);
			#ifdef WIN32
			throw std::exception(warBuf);
			#else
			throw std::domain_error(warBuf);
			#endif
		}
		break;
		}
		return 1;
	}
	catch (const std::exception& e)
	{
		CLogger::createInstance()->Log(MsgError,
			"AddFrameDef(%s,%d) func error[%s]. [%s %s %d]"
			, pBuf, len
			, e.what()
			, __FILE__, __FUNCTION__, __LINE__);
	}
	catch (...)
	{
		CLogger::createInstance()->Log(MsgFatal,
			"AddFrameDef(%s,%d) func error. [%s %s %d]"
			, pBuf, len
			, __FILE__, __FUNCTION__, __LINE__);
	}
	return -1;
};